import logging
import os
import time
from uuid import uuid1

from concurrent_log_handler import ConcurrentRotatingFileHandler
from flask import request, g

from apps.utils.MTimedRotatingFileHandler import MTimedRotatingFileHandler
from .logger_config import LOG_PATH, LOG_NAME, LGO_CONFIG


class WebLogger:

    def __init__(self, app=None):
        self.loggers = {}
        self.init()
        if app:
            self.init_app(app)

    def init(self):
        """
        默认配置 防止init_app没有读取
        :return:
        """
        self.self_logfile = "{}/logger_server.log".format(LOG_PATH)
        self.get_log_name = "logger_server"
        self.kwargs = {
            "set_level": logging.DEBUG,
            "logfile": self.self_logfile,
            "get_log_name": self.get_log_name,
            "formatter": '%(asctime)s %(levelname)s %(message)s'
        }
        self.logger = self.set_logger(self.kwargs)

    def init_app(self, app):

        for items in LGO_CONFIG:
            filename = os.path.abspath("{}/{}".format(LOG_PATH, items["file"]))
            self.kwargs = {"set_level": items["level"],
                           "logfile": filename,
                           "get_log_name": items["name"],
                           "formatter": items["formatter"]}
            self.set_logger(self.kwargs)

        self.logger = self.loggers.get(LOG_NAME)

        @app.before_request
        def before_request_log():
            """
            DEFORE REQUEST
            :return:
            """

            global _weblog_g
            _weblog_g = {"log": {}}
            st = time.time()
            # "{}{}".format(st, randint(1, 1000000))
            request_id = str(uuid1())
            request_id = "".join(request_id.split("-")[:-1])
            _weblog_g["log"]['request_id'] = request_id
            g.weblog_id = _weblog_g["log"]['request_id']
            g.weblog = _weblog_g
            _weblog_g["log"]['st'] = st
            _weblog_g["log"]['ip'] = request.remote_addr
            _weblog_g["log"]['url'] = request.url

        @app.after_request
        def after_request_id(response):
            response.headers["request_id"] = g.weblog_id
            return response

        @app.teardown_request
        def teardown_request_log(exception):
            """
            Teardown request
            :param exception:
            :return:
            """
            try:
                _weblog_g["log"]["method"] = request.method
                _weblog_g["log"]["jsondata"] = request.json
                diff = (time.time() - _weblog_g["log"]['st']) * 1000
                _weblog_g["log"]['t_diff'] = "{} ms".format((round(diff, 3)))
                self.info("[api|view] {}".format(_weblog_g["log"]))
                if exception:
                    self.error(_weblog_g["log"])
                    self.exception(exception)
            except Exception as e:
                _weblogger_error = {"type": "weblogger error", "exceptione": e}
                self.error(_weblogger_error)

    def set_logger(self, kwargs):
        set_level = kwargs.get("set_level")
        logfile = kwargs.get("logfile")
        get_log_name = kwargs.get("get_log_name")
        formatter = kwargs.get("formatter")
        if not os.path.exists(os.path.split(logfile)[0]):
            os.makedirs(os.path.split(logfile)[0])
        # file_handler = MTimedRotatingFileHandler(logfile, "midnight", 1, 7)
        file_handler = ConcurrentRotatingFileHandler(logfile, "a", 512*1024, 5)
        file_handler.suffix = "%Y-%m-%d"
        file_handler.setLevel(set_level)
        _formatter = logging.Formatter(formatter)
        file_handler.setFormatter(_formatter)
        logging.getLogger(get_log_name).addHandler(file_handler)
        logging.getLogger(get_log_name).setLevel(logging.DEBUG)
        logg = logging.getLogger(get_log_name)
        self.loggers[get_log_name] = {
            "critical": logg.critical,
            "error": logg.error,
            "warning": logg.warning,
            "info": logg.info,
            "debug": logg.debug,
            "exception": logg.exception
        }
        return self.loggers[get_log_name]

    def debug(self, log):
        self.logger["debug"](log)

    def info(self, log):
        self.logger["info"](log)

    def warning(self, log):
        self.logger["warning"](log)

    def error(self, log):
        self.logger["error"](log)

    def critical(self, log):
        self.logger["critical"](log)

    def exception(self, log):
        self.logger["exception"](log)


weblog = WebLogger()
